﻿#include <cmath>

#include "MathVector2d.h"

template class MathVector2d<float>;

  //some weird code that makes this class work with template parameter float
template float cos( const MathVector2d<float>& a, const MathVector2d<float>&b );
template MathVector2d<float> operator + ( const MathVector2d<float>& a, const MathVector2d<float>& b );
template MathVector2d<float> operator - ( const MathVector2d<float>& a, const MathVector2d<float>& b );
template float operator * ( const MathVector2d<float>& a, const MathVector2d<float>& b );
template MathVector2d<float> operator * ( const MathVector2d<float>& a , const float& b );
template MathVector2d<float> operator * ( const float& b, const MathVector2d<float>& a );
template MathVector2d<float> operator / ( const MathVector2d<float>& a, const float& b );
template bool operator == ( const MathVector2d<float>& a, const MathVector2d<float>& b );
template bool operator != ( const MathVector2d<float>& a, const MathVector2d<float>& b );
template MathVector2d<float> projection( const MathVector2d<float>& a, const MathVector2d<float>& b );
template MathVector2d<float> set_length( const MathVector2d<float>& a, const float& b );

  // vector length
template<class T>
T MathVector2d<T> :: length() const{
    return sqrt( get_x() * get_x() + get_y() * get_y() );
}

  // vectors angle cosine
template<class T>
T cos( const MathVector2d<T>& a, const MathVector2d<T>&b ){
    return ( ( a * b ) / ( a.length() * b.length() )  );
}

  // vector sum
template<class T>
MathVector2d<T> operator + ( const MathVector2d<T>& a, const MathVector2d<T>& b ){
     return MathVector2d<T>( a.get_x() + b.get_x(), a.get_y() + b.get_y () );
}

  // vector margin
template<class T>
MathVector2d<T> operator - ( const MathVector2d<T>& a, const MathVector2d<T>& b ){
    return MathVector2d<T>( (a.get_x() - b.get_x() ), (a.get_y() - b.get_y () ) );
}

  // scalar product
template<class T>
T operator * ( const MathVector2d<T>& a, const MathVector2d<T>& b ){
    return ( a.get_x() * b.get_x() + a.get_y() * b.get_y() );
}

  // vector multyplied by number
template<class T>
MathVector2d<T> operator * ( const MathVector2d<T>& a , const float& b ){
    return MathVector2d<T>( ( a.get_x() * b ), ( a.get_y() * b ) );
}

template<class T>
MathVector2d<T> operator * ( const float& b, const MathVector2d<T>& a ){
    return a * b;
}

template<class T>
MathVector2d<T> operator / ( const MathVector2d<T>& a, const float& b ){
    return ( a * ( 1 / b ) );
}

  // if vectors are same returns true else returns false
template<class T>
bool operator == ( const MathVector2d<T>& a, const MathVector2d<T>& b ){
    return ( (a.get_x() == b.get_x() ) && (a.get_y() == b.get_y() ) );
}

  // if vectors aren't same returns true else returns false
template<class T>
bool operator != ( const MathVector2d<T>& a, const MathVector2d<T>& b ){
    return !( a == b );
}

  // projection of a vector on vector b
template<class T>
MathVector2d<T> projection( const MathVector2d<T>& a, const MathVector2d<T>& b ){
    return ( ( b * a.length() * cos( a, b ) ) / ( b.length() ) );
}

  // sets vector's length to b
template<class T>
MathVector2d<T> set_length( const MathVector2d<T>& a, const float& b ){
    return ( ( a * b ) / a.length() ) ;
}
